/*
 * Copyright 2011 Philippe Blanc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package me.l1k3.app.fx.demo.client;

import me.l1k3.core.client.Color;
import me.l1k3.fx.client.*;
import me.l1k3.fx.client.channel.*;
import me.l1k3.fx.client.channel.inter.DimensionConstant.AnchorHorizontal;
import me.l1k3.fx.client.channel.inter.DimensionConstant.AnchorVertical;
import me.l1k3.fx.client.channel.inter.DimensionConstant.Direction;
import me.l1k3.fx.client.engine.inter.FXEngine;
import me.l1k3.fx.client.event.FXEvent;
import me.l1k3.fx.client.event.FXEventHandler;
import me.l1k3.fx.client.inter.FXEx;
import me.l1k3.parameter.client.Callback;
import me.l1k3.parameter.client.Parameter;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Element;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Window;

public class Demo implements EntryPoint {
    protected Element info;
    
    @Override
	public void onModuleLoad() {
        info = DOM.getElementById("info");
        
        //see VisualFox-Parameter
        Parameter.load("effect", new Callback() {
            @Override
            public void run(JavaScriptObject js) {
                load(js);
            }
        });
    }
    
    private void load(JavaScriptObject js) {
        Parameters parameters = js.cast();
        
        if(parameters.get("background", true)) {
            animeCubeBackground();
            animeColorBackground();
            animeRenardBackground();
            animeBgBackground();
            animeVisualBackground();
        }
        
        if(parameters.get("fox", false)) {
            fox(parameters);
        }
	}
	
	private void fox(Parameters parameters) {
	    Element element = DOM.getElementById("fox");
        
        if(element==null) return;
        
        FXEx f;
        int mode = parameters.get("mode", 0);
        
        switch(mode) {
            case 0:
                f = FXFade.range(element);
                Window.setTitle("VisualFox-FX | FXFade");
            break;
            case 1:
                f = FXHighlight.highlight(element, new Color(255,255,0), new Color(255,0,255));
                Window.setTitle("VisualFox-FX | FXHighlight");
            break;
            case 2:
                f = FXHighlight.highlight(element, new Color(255,0,255));
                Window.setTitle("VisualFox-FX | FXHighlight");
            break;
            case 3:
                f = FXReveal.reveal(element);
                Window.setTitle("VisualFox-FX | FXReveal");
            break;
            case 4:
                f = FXReveal.reveal(element, Direction.HORIZONTAL);
                Window.setTitle("VisualFox-FX | FXReveal");
            break;
            case 5:
                f = FXOpen.open(element, Direction.HORIZONTAL);
                Window.setTitle("VisualFox-FX | FXOpen");
            break;
            case 6:
                f = FXPosition.to(element, 400, 20);
                Window.setTitle("VisualFox-FX | FXPosition");
            break;
            case 7:
                f = FXDimension.to(element, 0, 0);
                Window.setTitle("VisualFox-FX | FXDimension");
            break;
            case 8:
                f = FXDimension.to(element, 0, 0);
                Window.setTitle("VisualFox-FX | FXDimension");
            break;
            case 9:
                f = FXBox.box(element);
                Window.setTitle("VisualFox-FX | FXBox");
            break;
            case 10:
                f = FXClip.clip(element);
                Window.setTitle("VisualFox-FX | FXClip");
            break;
            default:
                FXChannel channel = FXChannel.create(element);
                
                channel.add(OpacityChannel.smartRange(channel.getType(), element, 1, 0.5)); //smartRange(element) take in account the state of the element's opacity
                channel.add(ClipChannel.clip(channel.getType(), Direction.HORIZONTAL, AnchorHorizontal.RIGHT, AnchorVertical.CENTER));
                channel.add(OpenChannel.vertical(channel.getType()));
                channel.add(ColorChannel.range(channel.getType(), new Color(0,0,0), new Color(255,255,255)));
                channel.add(ColorChannel.rangeBackground(channel.getType(), new Color(0,255,0), new Color(255,0,0)));
                
                f = channel;
                Window.setTitle("VisualFox-FX | FXChannel");
            break;
        }
        
        //change easing
        //f.setEasing(FXEngine.EASE_OUT);

        //let's add a listener...
        f.addFXEventHandler(new FXEventHandler() {
            @Override
            public void onStart(FXEvent event) {
                print("onStart\t\t"+event.getFX());
            }
            
            @Override
            public void onComplete(FXEvent event) {
                print("onComplete\t"+event.getFX());
            }
        });
        
        //static method to change opacity of an element
        //FXFade.setOpacity(element, 0.5);
        
        if(f instanceof FXOpen) {
            //((FXOpen)f).show(2000, 0, true);
            //((FXOpen)f).hide(2000);
        }
        
        if(f instanceof FXReveal) {
            //((FXReveal)f).show(2000, 0, true);
            //((FXReveal)f).hide(2000);
        }
        
        //x loops (default 10) with a pause of 1s in between - yo-yo mode
        int max = parameters.get("loops", 10);
        final FXLoops loops = new FXLoops(f, max, 1000, true);
        
        //let's add a listener...
        loops.addFXEventHandler(new FXEventHandler() {
            @Override
            public void onStart(FXEvent event) {
                print("loops onStart\t\t"+event.getFX());
            }
            
            @Override
            public void onComplete(FXEvent event) {
                print("loops onComplete\t"+event.getFX());
            }
        });
        
        //each one of the 10 animation is set to 2s with an initial starting pause of 2.5s
        loops.animate(2000, 2500, false).callback(new Command() {
            @Override
            public void execute() {
                print("Callback: loops ended\t"+loops.toString());
            }
        });
	}
	
	private void animeColorBackground() {
        Element element = DOM.getElementById("color");
        FXChannel color = FXChannel.create(element);
        color.add(ColorChannel.rangeBackground(color.getType(), new Color(0,0,0), new Color(255,0,0)));
        color.add(OpacityChannel.smartRange(color.getType(), element, 1, 0));
        
        FXLoops loops = new FXLoops(color, FXLoops.INFINITY, 500, true);
        loops.animate(1000);
    }
	
	private void animeCubeBackground() {
	    Element element = DOM.getElementById("qbert");
        FXChannel cube = FXChannel.create(element);
        cube.setEasing(FXEngine.EASE);
        cube.add(BackgroundPositionExChannel.byIncrementEx(cube.getType(), -400, 0));
        
        FXLoops loops = new FXLoops(cube, FXLoops.INFINITY, 0, true);
        loops.animate(8000);
    }
	
	private void animeRenardBackground() {
	    Element element = DOM.getElementById("renard");
        FXChannel renard = FXChannel.create(element);
        renard.setEasing(FXEngine.EASE);
        renard.add(BackgroundPositionExChannel.byIncrementEx(renard.getType(), 0, -400));

        FXLoops loops = new FXLoops(renard, FXLoops.INFINITY, 0, true);
        loops.animate(8000);
    }
	
	private void animeBgBackground() {
	    Element element = DOM.getElementById("bg");
        FXChannel bg = FXChannel.create(element);
        bg.setEasing(FXEngine.EASE);
        bg.add(BackgroundPositionChannel.byIncrement(bg.getType(), 600, 0));
        bg.add(OpacityChannel.smartRange(bg.getType(), element, 1, 0.1));
        
        FXLoops loops = new FXLoops(bg, FXLoops.INFINITY, 0, true);
        loops.animate(8000);
    }
	
	private void animeVisualBackground() {
	    Element element = DOM.getElementById("visual");
        FXChannel visual = FXChannel.create(element);
        visual.add(BackgroundPositionChannel.byIncrement(visual.getType(), 0, 600));
        visual.add(OpacityChannel.smartRange(visual.getType(), element, 1, 0.1));
        
        FXLoops loops = new FXLoops(visual, FXLoops.INFINITY, 1000, true);
        loops.animate(8000);
    }
	
	private void print(String message) {
        if(info!=null) {
            info.setInnerText(message);
        }
        
        System.out.println(message);
	}
	
	protected static class Parameters extends JavaScriptObject {
	    
	    protected Parameters() {
	        
	    }
	    
	    public final native String get(String key, String defaultValue) /*-{
	        return this[key] || defaultValue;
	    }-*/;
	    
	    public final native boolean get(String key, boolean defaultValue) /*-{
	        return this[key] || defaultValue;
	    }-*/;
	    
	    public final native int get(String key, int defaultValue) /*-{
	        return this[key] || defaultValue;
	    }-*/;
	    
	    public final native double get(String key, double defaultValue) /*-{
	        return this[key] || defaultValue;
	    }-*/;
	}
}
